#include "../mqserver/virtualhost.hpp"

#include <gtest/gtest.h>

using empty_map = std::unordered_map<std::string, std::string>;

class HostTest: public testing::Test
{
public:
    virtual void SetUp() override
    {
        _host = std::make_shared<mymq::VirtualHost>("host1", "./data/host1/message", "./data/host1/meta.db");
        _host->DeclareExchange("exchange1", mymq::ExchangeType::DIRECT, true, false, empty_map());
        _host->DeclareExchange("exchange2", mymq::ExchangeType::DIRECT, true, false, empty_map());
        _host->DeclareExchange("exchange3", mymq::ExchangeType::DIRECT, true, false, empty_map());

        _host->DeclareQueue("queue1", true, false, false, empty_map());
        _host->DeclareQueue("queue2", true, true, false, empty_map());
        _host->DeclareQueue("queue3", true, true, false, empty_map());

        _host->Bind("exchange1", "queue1", "news.music.#");
        _host->Bind("exchange1", "queue2", "news.music.#");
        _host->Bind("exchange1", "queue3", "news.music.#");

        _host->Bind("exchange2", "queue1", "news.music.#");
        _host->Bind("exchange2", "queue2", "news.music.#");
        _host->Bind("exchange2", "queue3", "news.music.#");

        _host->Bind("exchange3", "queue1", "news.music.#");
        _host->Bind("exchange3", "queue2", "news.music.#");
        _host->Bind("exchange3", "queue3", "news.music.#");

        _host->Publish("queue1", nullptr, "Hello World-1");
        _host->Publish("queue1", nullptr, "Hello World-2");
        _host->Publish("queue1", nullptr, "Hello World-3");

        _host->Publish("queue2", nullptr, "Hello World-1");
        _host->Publish("queue2", nullptr, "Hello World-2");
        _host->Publish("queue2", nullptr, "Hello World-3");

        _host->Publish("queue3", nullptr, "Hello World-1");
        _host->Publish("queue3", nullptr, "Hello World-2");
        _host->Publish("queue3", nullptr, "Hello World-3");
    }
    virtual void TearDown() override
    {
        _host->Clear();
        std::cout << "完成资源的清理化工作" << std::endl;
    }
public:
    mymq::VirtualHost::ptr _host;
};

TEST_F(HostTest, init_test)
{
    ASSERT_EQ(_host->ExistsExchange("exchange1"), true);
    ASSERT_EQ(_host->ExistsExchange("exchange2"), true);
    ASSERT_EQ(_host->ExistsExchange("exchange3"), true);

    ASSERT_EQ(_host->ExistsQueue("queue1"), true);
    ASSERT_EQ(_host->ExistsQueue("queue2"), true);
    ASSERT_EQ(_host->ExistsQueue("queue3"), true);

    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue1"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue2"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue3"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange2", "queue1"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange2", "queue2"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange2", "queue3"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange3", "queue1"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange3", "queue2"), true);
    ASSERT_EQ(_host->ExistsBinding("exchange3", "queue3"), true);

    mymq::MessagePtr msg1 = _host->Consume("queue1");
    ASSERT_EQ(msg1->payload().body(), "Hello World-1");
    mymq::MessagePtr msg2 = _host->Consume("queue1");
    ASSERT_EQ(msg2->payload().body(), "Hello World-2");
    mymq::MessagePtr msg3 = _host->Consume("queue1");
    ASSERT_EQ(msg3->payload().body(), "Hello World-3");
    mymq::MessagePtr msg4 = _host->Consume("queue1");
    ASSERT_EQ(msg4.get(), nullptr);
}

TEST_F(HostTest, delete_exchange)
{
    _host->DeleteExchange("exchange1");
    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue2"), false);
    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue3"), false);
}

TEST_F(HostTest, delete_queue)
{
    _host->DeleteQueue("queue1");
    ASSERT_EQ(_host->ExistsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->ExistsBinding("exchange2", "queue1"), false);
    ASSERT_EQ(_host->ExistsBinding("exchange3", "queue1"), false);
    mymq::MessagePtr msg1 = _host->Consume("queue1");
    ASSERT_EQ(msg1.get(), nullptr);
}

TEST_F(HostTest, ack_queue)
{
    mymq::MessagePtr msg1 = _host->Consume("queue1");
    ASSERT_EQ(msg1->payload().body(), "Hello World-1");
    _host->Ack("queue1", msg1->payload().properties().id());

    mymq::MessagePtr msg2 = _host->Consume("queue1");
    ASSERT_EQ(msg2->payload().body(), "Hello World-2");
    _host->Ack("queue1", msg2->payload().properties().id());

    mymq::MessagePtr msg3 = _host->Consume("queue1");
    ASSERT_EQ(msg3->payload().body(), "Hello World-3");
    _host->Ack("queue1", msg3->payload().properties().id());
}

int main(int argc, char* argv[])
{
    testing::InitGoogleTest(&argc, argv);
    RUN_ALL_TESTS();

    return 0;
}